using System;
using System.Collections.Generic;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;

#pragma warning disable 1591

namespace Creek.UI.ExceptionReporter.Core
{
    /// <summary>
    /// a bag of information (some of which is stored and retrieved from config)
    /// </summary>
    public class ExceptionReportInfo : Disposable
    {
        #region EmailMethod enum

        /// <summary>
        /// Enumerated type used to represent supported e-mail mechanisms 
        /// </summary>
        public enum EmailMethod
        {
            SimpleMAPI,
            SMTP
        };

        #endregion

        private readonly List<Exception> _exceptions = new List<Exception>();

        public ExceptionReportInfo()
        {
            SetDefaultValues();
        }

        /// <summary>
        /// The Main (for the most part the 'only') exception, which is the subject of this exception 'report'
        /// Setting this property will clear any previously set exceptions
        /// <remarks>If multiple top-level exceptions are required, use SetExceptions instead</remarks>
        /// </summary>
        public Exception MainException
        {
            get { return _exceptions.Count > 0 ? _exceptions[0] : null; }
            set
            {
                _exceptions.Clear();
                _exceptions.Add(value);
            }
        }

        public IList<Exception> Exceptions
        {
            get { return _exceptions.AsReadOnly(); }
        }

        public string CustomMessage { get; set; }
        public string SmtpUsername { get; set; }
        public string SmtpPassword { get; set; }
        public string SmtpFromAddress { get; set; }
        public string SmtpServer { get; set; }

        /// <summary>
        /// Email that is displayed in the 'Contact Information'. See <see cref="EmailReportAddress"/> 
        /// for the email actually used to send if using SimpleMAPI or SMTP)
        /// </summary>
        public string ContactEmail { get; set; }

        /// <summary>
        /// The name of the running application using <see cref="Application.ProductName"/>
        /// </summary>
        public string AppName { get; set; }

        /// <summary>
        /// The version of the running application using <see cref="Application.ProductVersion"/>
        /// </summary>
        public string AppVersion { get; set; }

        /// <summary>
        /// Region information using <see cref="Application.CurrentCulture.DisplayName"/>
        /// </summary>
        public string RegionInfo { get; set; }

        /// <summary>
        /// The name of the running application's machine using <see cref="Environment.MachineName"/>
        /// </summary>
        public string MachineName { get; set; }

        /// <summary>
        /// The name of the running application's current user. Defaults to <see cref="Environment.UserName"/>
        /// </summary>
        public string UserName { get; set; }

        public DateTime ExceptionDate { get; set; }

        /// <summary>
        /// The text filled in by the user of the Exception Reporter dialog
        /// </summary>
        public string UserExplanation { get; set; }

        /// <summary>
        /// The calling assembly of the running application
        /// If not set, will default to <see cref="Assembly.GetEntryAssembly()"/> ?? <see cref="Assembly.GetCallingAssembly()"/>
        /// </summary>
        public Assembly AppAssembly { get; set; }

        public string WebUrl { get; set; }
        public string Phone { get; set; }
        public string Fax { get; set; }

        /// <summary>
        /// The company/owner of the running application.
        /// Used in the dialog label that reads '...please contact {0} support'
        /// </summary>
        public string CompanyName { get; set; }

        public bool ShowGeneralTab { get; set; }
        public bool ShowConfigTab { get; set; }
        public bool ShowContactTab { get; set; }
        public bool ShowExceptionsTab { get; set; }
        public bool ShowSysInfoTab { get; set; }
        public bool ShowAssembliesTab { get; set; }

        /// <summary>
        /// Email address used to send an email (eg appears in the 'to:' field in the default email client if simpleMAPI)
        /// </summary>
        public string EmailReportAddress { get; set; }

        /// <summary>
        /// Default is <see cref="DefaultLabelMessages.DefaultExplanationLabel"/>
        /// </summary>
        public string UserExplanationLabel { get; set; }

        public string ContactMessageTop { get; set; }

        public bool ShowFlatButtons { get; set; }
        public bool ShowLessMoreDetailButton { get; set; }
        public bool ShowFullDetail { get; set; }
        public bool ShowButtonIcons { get; set; }

        /// <summary>
        /// Dialog title text
        /// </summary>
        public string TitleText { get; set; }

        public Color BackgroundColor { get; set; }
        public float UserExplanationFontSize { get; set; }

        /// <summary>
        /// Take a screenshot automatically at the point of calling <see cref="ExceptionReporter.Show(System.Exception[])"/>
        /// which will then be available if sending an email using the ExceptionReporter dialog functionality
        /// </summary>
        public bool TakeScreenshot { get; set; }

        /// <summary>
        /// The Screenshot Bitmap, used internally
        /// </summary>
        public Bitmap ScreenshotImage { get; set; }

        /// <summary>
        /// Which email method to use (SMTP or SimpleMAPI) 
        /// SimpleMAPI basically means it will try to use an installed Email client on the user's machine (eg Outlook)
        /// </summary>
        public EmailMethod MailMethod { get; set; }

        /// <summary>
        /// Whether a screenshot is configured to be taken and that it has been taken - used internally
        /// </summary>
        public bool ScreenshotAvailable
        {
            get { return TakeScreenshot && ScreenshotImage != null; }
        }

        /// <summary>
        /// Any files to attach to email (SMTP or SimpleMAPI) 
        /// This is in addition to the automatically attached screenshot, if configured via TakeScreenshot
        /// Any file attached needs to be a registered MIME type extension to work(?)
        /// (attaching .tmp doesn't get attached in SimpleMAPI - testing using Outlook2013)
        /// </summary>
        public string[] FilesToAttach { get; set; }

        /// <summary>
        /// Add multiple exceptions to be shown (each in a separate tab if shown in dialog)
        /// <remarks>
        /// Note: Showing multiple exceptions is a special-case requirement - for only 1 top-level exception
        /// use the <see cref="MainException"/> property instead
        /// </remarks>
        /// </summary>
        public void SetExceptions(IEnumerable<Exception> exceptions)
        {
            _exceptions.Clear();
            _exceptions.AddRange(exceptions);
        }

        private void SetDefaultValues()
        {
            ShowFlatButtons = true;
            ShowFullDetail = true;
            ShowButtonIcons = true;
            BackgroundColor = Color.WhiteSmoke;
            ShowExceptionsTab = true;
            ShowContactTab = false;
            ShowConfigTab = true;
            ShowAssembliesTab = true;
            ShowSysInfoTab = true;
            ShowGeneralTab = true;
            UserExplanationLabel = DefaultLabelMessages.DefaultExplanationLabel;
            ContactMessageTop = DefaultLabelMessages.DefaultContactMessageTop;
            EmailReportAddress = "support@acompany.com";
                // SimpleMAPI won't work if this is blank, so show dummy place-holder
            TitleText = "Exception Report";
            UserExplanationFontSize = 12f;
            TakeScreenshot = false;
            FilesToAttach = new string[] {};
        }

        protected override void DisposeManagedResources()
        {
            if (ScreenshotImage != null)
            {
                ScreenshotImage.Dispose();
            }
            base.DisposeManagedResources();
        }
    }

    public static class DefaultLabelMessages
    {
        public const string DefaultExplanationLabel =
            "Please enter a brief explanation of events leading up to this exception";

        public const string DefaultContactMessageTop =
            "The following details can be used to obtain support for this application";
    }
}

#pragma warning restore 1591